#include "FLOAT.h"
#include <stdint.h>  
typedef union{
    struct{
        uint32_t m : 23;
        uint32_t e : 8;
        uint32_t s : 1;
    };
    uint32_t val;
}Float;

#define _sign(x) ((x) & 0x80000000) 

FLOAT F_mul_F(FLOAT a, FLOAT b) {
    int64_t scale = ((int64_t)a * (int64_t)b) >> 16; 
    return scale;
}

FLOAT F_div_F(FLOAT a, FLOAT b) {
	    FLOAT q, r;
    __asm__ __volatile__("idiv %2" 
                            : "=a"(q), "=d"(r) 
                            : "r"(b), "a"(a << 16), "d"(a >> 16)); 
    return q;
}

FLOAT f2F(float a) {
	 Float f;
    void *temp = &a;
    f.val = *(uint32_t *)temp; 
    uint32_t m = f.m | (1 << 23); 
    int shift = 134 - (int)f.e; 
    if(shift < 0) m <<= (-shift); 
    else m >>= shift; 
    return (_sign(f.val) ? -m : m);
}


FLOAT Fabs(FLOAT a) {
	return _sign(a) ? -(a) : (a);
}

/* Functions below are already implemented */

FLOAT sqrt(FLOAT x) {
	 FLOAT dt, t = int2F(2);
    do {
        dt = F_div_int((F_div_F(x, t) - t), 2);
        t += dt;
    } while(Fabs(dt) > f2F(1e-4));
    return t;
}

FLOAT pow(FLOAT x, FLOAT y) {
	  FLOAT t2, dt, t = int2F(2);
    do {
        t2 = F_mul_F(t, t);
        dt = (F_div_F(x, t2) - t) / 3;
        t += dt;
    } while(Fabs(dt) > f2F(1e-4));
    return t;
}

